package kernel_gui.gui.extended;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;

import kernel_gui.gui.generic.graphic.AnswersFrame;

import common.entities.enums.PATTERN;
import common.entities.persistent.Actor;
import common.entities.persistent.Genre;
import common.entities.persistent.Movie;

@SuppressWarnings("serial")
public class EAnswersFrame extends  AnswersFrame{

	public enum ANSWER_TYPE {Actor, Genre,  Movie};/*Country,Director - currently aren't returned as answers*/
	
	private ANSWER_TYPE answerType;
	private PATTERN questionPattern;
	private int parameterID;
	
	/*Data in shiat*/
	private DefaultTableModel currentTableModel;
	private List<Movie> movies = null;
	private List<Actor> actors = null;
	private List<Genre> genres = null;
	
	private int count = 0;
	private int currentPage = 0;
	private int currentPageCount = 0;
	private int totalPages = 0;
	private int numberOfRecordsPerPage;
	
	public EAnswersFrame(PATTERN questionPattern, int parameterID){
		/*Command to execute on cancel*/
		setExecuteOnCancel(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				Component components[] = MainPanel.getComponents();
				for (Component c : components) {
					if(c instanceof JPanel){
						JPanel panel = (JPanel) c;
						Component pcomponents[] = panel.getComponents();
						for(Component pc : pcomponents){
							if(pc instanceof JPanel){
								JPanel anotherPanel = (JPanel) pc;
								Component pccomponents[] = anotherPanel.getComponents();
								for(Component pcc : pccomponents){
									pcc.setEnabled(true);
								}
							}
							pc.setEnabled(true);
						}
					}
					
					c.setEnabled(true);
				}
				updateButtonsAndLabelsAfterReturnedResultSet();
			}
		});
		
		/*Command to execute before long request*/
		setExecuteBeforeLongRequest(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				Component components[] = MainPanel.getComponents();
				for (Component c : components) {
					if(c instanceof JPanel){
						JPanel panel = (JPanel) c;
						Component pcomponents[] = panel.getComponents();
						for(Component pc : pcomponents){
							if(pc instanceof JPanel){
								JPanel anotherPanel = (JPanel) pc;
								Component pccomponents[] = anotherPanel.getComponents();
								for(Component pcc : pccomponents){
									pcc.setEnabled(false);
								}
							}
							pc.setEnabled(false);
						}
					}
					c.setEnabled(false);
				}
			}
		});
		
		this.questionPattern = questionPattern;
		this.parameterID = parameterID;
		
		switch(questionPattern){
			case ACTOR_PLAYED_IN_MOVIE:
				answerType = ANSWER_TYPE.Actor;
				break;
			case GENRE_OF_MOVIE:
				answerType = ANSWER_TYPE.Genre;
				break;
			case MOVIE_ACTOR_IN:
				answerType = ANSWER_TYPE.Movie;
				break;
			case MOVIE_DIRECTED_BY:
				answerType = ANSWER_TYPE.Movie;
				break;
			case MOVIE_RELEASED_IN_YEAR:
				answerType = ANSWER_TYPE.Movie;
				break;
		}
		
		switch(answerType){
		case Actor:
			this.setTitle("Choose " + ANSWER_TYPE.Actor.toString() + " Answer");
			break;
		case Movie:
			this.setTitle("Choose " + ANSWER_TYPE.Movie.toString() + " Answer");
			break;
		case Genre:
			this.setTitle("Choose " + ANSWER_TYPE.Genre.toString() + " Answer");
			break;			
		}
		
		/*Update the numberOfRecords variable*/
		NumOfRecordsInPageComboBox.setSelectedIndex(2);
		numberOfRecordsPerPage = Integer.parseInt(NumOfRecordsInPageComboBox.getSelectedItem().toString());
		
		
		countResultAndPopulateTable(1);
	}
	
	private void initTableModel(){
		switch(this.answerType){
		case Actor:
			currentTableModel = new DefaultTableModel(new Object[][]{}, new Object[]{"First Name", "Last Name", "Sex"});
			break;
		case Movie:
			currentTableModel = new DefaultTableModel(new Object[][]{}, new Object[]{"Title", "Release Year", "Rank"});
			break;
		case Genre:
			currentTableModel = new DefaultTableModel(new Object[][]{}, new Object[]{"Genre Name"});
			break;
		}
		
		ResultTable.setModel(currentTableModel);
	}
	
 	protected void countResultAndPopulateTable(int page){
		
		final int pageWhenFinished = page;
		/*Command to execute after returning from*/
		int requestID = executeBeforeLongRequest(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				/*Updated count & labels*/
				EAnswersFrame.this.count = Integer.parseInt(answer.toString());
				EAnswersFrame.this.FoundNumberLabel.setText(String.valueOf(EAnswersFrame.this.count));
				
				if(EAnswersFrame.this.count != 0)
					EAnswersFrame.this.currentPage = 1;
				else
					EAnswersFrame.this.currentPage = 0;
				
				EAnswersFrame.this.PageNumberLabel.setText(String.valueOf(EAnswersFrame.this.currentPage));
				EAnswersFrame.this.totalPages = (int) Math.ceil(((float)EAnswersFrame.this.count)/numberOfRecordsPerPage);
				EAnswersFrame.this.TotalPageNumberLabel.setText(String.valueOf(EAnswersFrame.this.totalPages));
									
				/*Get the data*/
				populateTableWithResults(pageWhenFinished);
				
			}
		});
	
		kernel.countAnswers(this.questionPattern, this.parameterID, requestID);
	}
	
	private void populateTableWithResults(int page){
		/*Command to execute after returning from*/
		
		final int pageNumberToSet = page;
		int requestID = executeBeforeLongRequest(new CommandToExecute() {
			
			@SuppressWarnings("unchecked")
			@Override
			public void command(Object answer) {
				if(answer != null){
					
					switch(answerType){
					case Actor:
						actors = (List<Actor>)answer;
						currentPageCount = actors.size();
						break;
					case Genre:
						genres = (List<Genre>)answer;
						currentPageCount = genres.size();
						break;
					case Movie:
						movies = (List<Movie>)answer;
						currentPageCount = movies.size();
						break;
					}
					
					/*Create new table model, and insert the rows*/
					initTableModel();
					
					Object[] rowData = null;
					for(int i = 0; i < currentPageCount; i++){
						/*Get data according to current slave*/
						switch(answerType){
							case Actor:{
								Actor actor = EAnswersFrame.this.actors.get(i);
								rowData = new Object[] {actor.getFirstName(), actor.getLastName(), actor.getSex().toString()};
								break;
							}case Genre:{
								Genre genre = EAnswersFrame.this.genres.get(i);
								rowData = new Object[] {genre.getName()};
								break;
							}case Movie:{
								Movie movie = EAnswersFrame.this.movies.get(i);
								rowData = new Object[] {movie.getTitle(), movie.getReleaseYear(), movie.getRank()};
							break;
							}
						}
						currentTableModel.insertRow(i, rowData);
					}
					
					
					if(EAnswersFrame.this.count != 0)
						currentPage = pageNumberToSet;
					else
						currentPage = 0;
					
					updateButtonsAndLabelsAfterReturnedResultSet();
				}
			}
		});
		
		int from = (page <= 0) ? 0 : (page-1)*numberOfRecordsPerPage;
		int to = (page <= 0) ? 0 : page*numberOfRecordsPerPage;
		
		kernel.getAnswers(this.questionPattern, this.parameterID, from, to, requestID);
	}
	
	private void updateButtonsAndLabelsAfterReturnedResultSet(){
		PageNumberLabel.setText(String.valueOf(currentPage));
		totalPages = (int) Math.ceil(((float)count)/numberOfRecordsPerPage);
		TotalPageNumberLabel.setText(String.valueOf(totalPages));
		
		if(totalPages == 0){
			NextButton.setEnabled(false);
			PreviousButton.setEnabled(false);
			NumOfRecordsInPageComboBox.setEnabled(false);
		}else{
			NextButton.setEnabled(true);
			PreviousButton.setEnabled(true);
			NumOfRecordsInPageComboBox.setEnabled(true);
		}
					
	}
	
	
	@Override
	protected void NumOfRecordsInPageComboBoxActionPerformed(ActionEvent evt) {
		numberOfRecordsPerPage = Integer.parseInt(NumOfRecordsInPageComboBox.getSelectedItem().toString());
		
		/*fix problem when the user is on page 100 in 5rec-per-page but there is no page 100 in 100rec-per-page*/
		int expectedTotalPages = (int) Math.ceil(((float)EAnswersFrame.this.count)/numberOfRecordsPerPage);

		
		if(currentPage > expectedTotalPages)
			currentPage = expectedTotalPages;
		
		populateTableWithResults(currentPage);		
	}

	@Override
	protected void NextButtonActionPerformed(ActionEvent evt) {
		if(currentPage < totalPages){
			int askingPage = currentPage+1;
			populateTableWithResults(askingPage);
		}else{
			populateTableWithResults(1);
		}		
	}

	@Override
	protected void PreviousButtonActionPerformed(ActionEvent evt) {
		if(currentPage > 1){
			int askingPage = currentPage-1;
			populateTableWithResults(askingPage);
		}else{
			populateTableWithResults(totalPages);
		}		
	}


	@Override
	protected void setWindowComponentsWhenCalledFromAnotherFrame() {
		/*not needed*/
		
	}

	@Override
	protected void BackButtonActionPerformed(ActionEvent evt) {
		if(isCalledAsLongRequestFromOtherFrame()){
			int selectedRowIndx = ResultTable.getSelectedRow();
			if(selectedRowIndx != -1 && ((answerType == ANSWER_TYPE.Actor && actors !=null) ||
					(answerType == ANSWER_TYPE.Movie && movies != null) || 
					(answerType == ANSWER_TYPE.Genre && genres != null))){
				switch(answerType){
				case Actor:
					this.setTitle("Choose " + ANSWER_TYPE.Actor.toString() + " Answer");
					setAnswerToCallingFrame(actors.get(ResultTable.convertRowIndexToModel(selectedRowIndx)));
					break;
				case Movie:
					setAnswerToCallingFrame(movies.get(ResultTable.convertRowIndexToModel(selectedRowIndx)));
					break;
				case Genre:
					setAnswerToCallingFrame(genres.get(ResultTable.convertRowIndexToModel(selectedRowIndx)));
					break;			
				}
				
			returnToCallingFrame();
			}else{
				int userClick = JOptionPane.showConfirmDialog(this, "Going back without choosing an answer will reset\n" +
						"the question you have formed.\nContinue?", "Choose an answer!", JOptionPane.YES_NO_OPTION);
				if(userClick == JOptionPane.YES_OPTION){
					setAnswerToCallingFrame(null);
					returnToCallingFrame();
				}
			}
		}
	}

}
